package com.ug.system.controller;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.ug.common.cache.redis.RedisCacheService;
import com.ug.common.constant.CommonConstants;
import com.ug.common.enums.HttpCode;
import com.ug.common.ratelimit.RateLimit;
import com.ug.common.ratelimit.RateLimitKey;
import com.ug.common.response.ResponseMessage;
import com.ug.common.response.ResponseMessageFactory;
import com.ug.common.utils.SocialUtils;
import com.ug.logs.annotation.Log;
import com.ug.system.entity.SysUser;
import com.ug.system.entity.properties.SocialLoginConfigProperties;
import com.ug.system.entity.properties.SocialProperties;
import com.ug.system.entity.vo.QuictLoginVO;
import com.ug.system.entity.vo.SysUserVO;
import com.ug.system.entity.dto.LoginDto;
import com.ug.system.service.LoginService;
import com.ug.system.service.SysUserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.model.AuthUser;
import me.zhyd.oauth.request.AuthRequest;
import me.zhyd.oauth.utils.AuthStateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;

/**
 * @Author LY
 * @create 2024/7/17 9:51
 * @Description 登录控制层
 */
@Tag(name = "LoginController", description = "登录管理")
@RestController
@RequiredArgsConstructor
@RequestMapping("/auth")
public class LoginController {

    private static final Logger logger = LoggerFactory.getLogger(LoginController.class);

    private final SysUserService userService;
    private final LoginService loginService;
    private final SocialProperties socialProperties;
    private final RedisCacheService redisCacheService;

    /**
     * 登录
     * @param loginDto 请求用户信息入参
     */
    @Operation(summary = "用户账号登录")
    @Log("用户账号登录")
    @PostMapping("/login")
    public ResponseMessage<Object> login(@RequestBody LoginDto loginDto){
        return ResponseMessageFactory.getSuccessResponseMessage(loginService.doLogin(loginDto));
    }

    /**
     * 快捷登录
     * @param uuid 快捷登录标识
     */
    @Operation(summary = "用户快捷登录")
    @Log("用户快捷登录")
    @PostMapping("/quickLogin")
    public ResponseMessage<Object> quickLogin(@RequestParam("uuid") String uuid){
        return ResponseMessageFactory.getSuccessResponseMessage(loginService.quickLogin(uuid));
    }

    /**
     * 用户注册
     * @param userDto 请求用户信息入参
     */
    @Operation(summary = "用户注册")
    @PostMapping("/register")
    public ResponseMessage<String> registerUser(@RequestBody SysUserVO userDto){
        userService.editUser(userDto);
        return ResponseMessageFactory.getSuccessResponseMessage("注册成功");
    }

    /**
     * 通过refreshToken得到新的token
     */
    @Operation(summary = "刷新Token")
    @PutMapping("/refresh")
    public ResponseMessage<String> refreshToken(HttpServletRequest request){
        String token = loginService.refreshToken(request);
        if (StrUtil.isNotEmpty(token)){
            return ResponseMessageFactory.getSuccessResponseMessage(token);
        }
        return ResponseMessageFactory.getSuccessResponseMessage("请重新登录");
    }

    /**
     * 获取验证码
     */
    @Operation(summary = "获取验证码")
    @RateLimit(key = RateLimitKey.LOGIN_CAPTCHA_KEY, time = 10, maxCount = 10,
            rateType = RateLimit.RateType.REDIS, limitType = RateLimit.LimitType.IP)
    @GetMapping("/code")
    public ResponseMessage<Object> getVerifyCode(){
        return ResponseMessageFactory.getSuccessResponseMessage(loginService.getVerifyCode());
    }

    /**
     * 第三方登录请求
     * @param source 登录来源
     */
    @GetMapping("/binding/{source}")
    public ResponseMessage<QuictLoginVO> authBinding(@PathVariable("source") String source){
        logger.info("第三方登录请求：{}", source);
        SocialLoginConfigProperties obj = socialProperties.getType().get(source);
        if (ObjectUtil.isNull(obj)) {
            return ResponseMessageFactory.getErrorResponseMessage(HttpCode.PARAMS_ERROR, source + "平台账号暂不支持");
        }
        AuthRequest authRequest = SocialUtils.getAuthRequest(source, socialProperties);
        String state = AuthStateUtils.createState();
        String authorizeUrl = authRequest.authorize(state);
        QuictLoginVO vo = new QuictLoginVO();
        vo.setUuid(state);
        vo.setUrl(authorizeUrl);
        return ResponseMessageFactory.getSuccessResponseMessage(vo, "操作成功");
    }

    /**
     * 第三方登录回调业务处理 绑定授权
     * @param request 请求体
     */
    @GetMapping("/social/callback")
    public String socialCallback(HttpServletRequest request){
        logger.info("第三方登录回调业务处理：{}", request.getQueryString());
        String code = request.getParameter("code");
        String state = request.getParameter("state");
        String source = request.getParameter("source");
        //  获取第三方登录信息
        AuthResponse<AuthUser> response = SocialUtils.loginAuth(
                source, code, state, socialProperties);
        AuthUser authUserData = response.getData();
        //  判断授权响应是否成功
        if (!response.ok()) {
            throw new RuntimeException(response.getMsg());
        }
        SysUser sysUser = new SysUser();
        sysUser.setOpenId(authUserData.getUuid());
        sysUser.setNickName(authUserData.getNickname());
        sysUser.setRegisterType(authUserData.getSource());
        //  第一次快捷登录时保存用户信息
        userService.saveUserByFirst(sysUser);
        //  缓存回调获得的openId登录的时候取出进行登录
        redisCacheService.put(state, authUserData.getUuid(), 60 * 5);
        //  前端页面弹窗关闭
        return CommonConstants.WINDOW_CLOSED;
    }
}
